﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Globalization;
using Microsoft.SharePoint.Utilities;
using System.Web.UI.WebControls;
using System.Diagnostics;
using Microsoft.SharePoint.Publishing;
using System.Web;

namespace LanguageConfigurationSolution
{
    public class RootLandingPage : Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase
    {

        private const string QualityValuePrefix = ";q=";

        protected override void OnLoad(EventArgs e)
        {
            try
            {
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    using (SPSite site = new SPSite(SPContext.Current.Site.ID))
                    {
                        string targetUrl = this.GetRedirectTargetUrl(site);
                        if (!string.IsNullOrEmpty(targetUrl))
                        {
                            Redirect(targetUrl);
                        }
                        else
                        {
                            try
                            {
                                using (SPWeb web = site.RootWeb.Webs[0])
                                {
                                    Redirect(web.ServerRelativeUrl);
                                }
                            }
                            catch
                            {
                                Label errorlabel = new Label();
                                errorlabel.Text = "No redirect for the language could take place";
                                Controls.Add(errorlabel);
                                EventLog.WriteEntry(this.GetType().FullName, "No redirect for the language could take place", EventLogEntryType.Warning);
                            }
                        }
                    }
                });
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Caused by the redirect
            }
            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    EventLog.WriteEntry(this.GetType().FullName, ex.ToString(), EventLogEntryType.Error);
                });
            }
        }

        private void Redirect(string targetUrl)
        {
            // Use default Sharepoint behaviour (302) when infopath and/or frontpage, otherwise can't connect.
            string userAgent = HttpContext.Current.Request.UserAgent.ToLowerInvariant();
            if (userAgent.Contains("infopath") || userAgent.Contains("frontpage"))
            {
                SPUtility.Redirect(targetUrl, SPRedirectFlags.Default, Context);
            }
            else
            {

                HttpContext.Current.Response.AddHeader("Location", targetUrl);
                HttpContext.Current.Response.StatusCode = 301;
                HttpContext.Current.Response.Status = "301 Moved Permanently";
            }

        }

        private string GetSubWebUrl(SPWeb web)
        {
            if (PublishingWeb.IsPublishingWeb(web))
            {
                PublishingWeb pweb = PublishingWeb.GetPublishingWeb(web);
                if (pweb.DefaultPage != null)
                {
                    return pweb.DefaultPage.ServerRelativeUrl;
                }
                else
                {
                    return pweb.Url;
                }
            }
            else
            {
                return web.ServerRelativeUrl;
            }
        }

        public const string DEFAULTSUBWEBPROPERTYNAME = "LanguageConfigurationDefaultSubWeb";
        public const string DEFAULTSUBWEBCOOKIENAME = "DefaultLanguageSubWeb";

        private string GetRedirectTargetUrl(SPSite site)
        {
            #region Retrieve redirect target based on cookie
            try
            {
                HttpCookie cookie = Page.Request.Cookies[DEFAULTSUBWEBCOOKIENAME];
                if (cookie != null)
                {
                    using (SPWeb web = site.RootWeb.Webs[cookie.Value])
                    {
                        if (web != null && web.Exists)
                        {
                            return GetSubWebUrl(web);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    EventLog.WriteEntry(this.GetType().FullName, "Unable to retrieve SubWeb from cookie\r\n" + ex.ToString(), EventLogEntryType.Warning);
                });
            }
            #endregion

            #region Retrieve redirect target based on BrowserLanguages
            foreach (string language in GetUserLanguages())
            {
                try
                {
                    CultureInfo ci = new CultureInfo(language);

                    #region Find the Language SubWeb with the TwoLetterIsoLanguageName
                    try
                    {
                        using (SPWeb web = site.RootWeb.Webs[ci.TwoLetterISOLanguageName])
                        {
                            if (web != null && web.Exists && web.Properties.ContainsKey("LanguageSubWeb"))
                            {
                                return GetSubWebUrl(web);
                            }
                        }
                    }
                    catch
                    {
                    }
                    #endregion

                    #region Find the Language SubWeb which has regionalsettings with the same TwoLetterIsoLanguageName
                    foreach (SPWeb web in site.RootWeb.Webs)
                    {
                        if (web.Properties.ContainsKey("LanguageSubWeb") && web.Locale.TwoLetterISOLanguageName == ci.TwoLetterISOLanguageName)
                        {
                            if (PublishingWeb.IsPublishingWeb(web))
                            {
                                PublishingWeb pweb = PublishingWeb.GetPublishingWeb(web);
                                if (pweb.DefaultPage != null)
                                {
                                    return pweb.DefaultPage.ServerRelativeUrl;
                                }
                                else
                                {
                                    return pweb.Url;
                                }
                            }
                            else
                            {
                                return web.ServerRelativeUrl;
                            }
                        }
                    }
                    #endregion
                }
                catch
                {
                    // Unable to parse the given language-identifier
                }
            }
            #endregion

            #region Determine the default Language SubWeb based upon an CustomProperty of the RootWeb
            try
            {
                string LanguageConfigurationDefaultSubWeb = site.RootWeb.Properties[DEFAULTSUBWEBPROPERTYNAME];
                if (!string.IsNullOrEmpty(LanguageConfigurationDefaultSubWeb))
                {
                    using (SPWeb web = site.RootWeb.Webs[LanguageConfigurationDefaultSubWeb])
                    {
                        return GetSubWebUrl(web);
                    }
                }
            }
            catch
            { }
            #endregion

            #region Determine the default Language SubWeb based upon the Regional Settings of the RootWeb
            try
            {
                foreach (SPWeb web in site.RootWeb.Webs)
                {
                    if (web.Properties.ContainsKey("LanguageSubWeb") && web.Locale.TwoLetterISOLanguageName == site.RootWeb.Locale.TwoLetterISOLanguageName)
                    {
                        return GetSubWebUrl(web);
                    }
                }
            }
            catch (Exception ex)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    EventLog.WriteEntry(this.GetType().FullName, ex.ToString(), EventLogEntryType.Warning);
                });
            }
            #endregion

            if (site.RootWeb.Webs.Count > 0)
            {
                string url = null;
                using (SPWeb web = site.RootWeb.Webs[0])
                {
                    url = web.ServerRelativeUrl;
                }
                return url;
            }
            else
            {
                return null;
            }
        }


        /// <summary>
        /// Retrieve the Preferred UserLanguages from the webbrowser client
        /// </summary>
        /// <returns>An array of UserLanguages (</returns>
        private string[] GetUserLanguages()
        {
            string[] browserPrefLanguages = Page.Request.UserLanguages;
            if (null != browserPrefLanguages)
            {
                // Strips off the quality parameters. Thus quality remains unused/ignored.
                int qualityIndexPos = -1;
                for (int i = 0; i < browserPrefLanguages.Length; i++)
                {
                    qualityIndexPos = browserPrefLanguages[i].IndexOf(QualityValuePrefix, StringComparison.Ordinal);
                    if (qualityIndexPos > 0)
                    {
                        browserPrefLanguages[i] = browserPrefLanguages[i].Substring(0, qualityIndexPos);
                    }
                }
            }
            return browserPrefLanguages;
        }

    }
}
